home *** CD-ROM | disk | FTP | other *** search
- /*
- File: "MPExceptionTest.c"
-
- Description: This is a application to test/demo the MT/MP MPDelayUntil API.
-
- Version: v0.0
-
- File Ownership:
-
- DRI: George Warner
-
- Other Contact:
-
- Technology: MultiTasking/MultiProcessing
-
- Copyright: © Copyright 2000 Apple Computer, Inc. All rights reserved.
-
- Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
- ("Apple") in consideration of your agreement to the following terms, and your
- use, installation, modification or redistribution of this Apple software
- constitutes acceptance of these terms. If you do not agree with these terms,
- please do not use, install, modify or redistribute this Apple software.
-
- In consideration of your agreement to abide by the following terms, and subject
- to these terms, Apple grants you a personal, non-exclusive license, under Apple’s
- copyrights in this original Apple software (the "Apple Software"), to use,
- reproduce, modify and redistribute the Apple Software, with or without
- modifications, in source and/or binary forms; provided that if you redistribute
- the Apple Software in its entirety and without modifications, you must retain
- this notice and the following text and disclaimers in all such redistributions of
- the Apple Software. Neither the name, trademarks, service marks or logos of
- Apple Computer, Inc. may be used to endorse or promote products derived from the
- Apple Software without specific prior written permission from Apple. Except as
- expressly stated in this notice, no other rights or licenses, express or implied,
- are granted by Apple herein, including but not limited to any patent rights that
- may be infringed by your derivative works or by other works in which the Apple
- Software may be incorporated.
-
- The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
- WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
- WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
- COMBINATION WITH YOUR PRODUCTS.
-
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
- OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
- (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- Writers:
-
- gaw - George Warner
-
- Change History (most recent first):
-
- <1> 02/29/00 gaw Initial build
-
- Author Initials:
-
- gaw - George Warner
-
- */
-
- //**************************************************
- #pragma mark #Includes
- //**************************************************
- #include <MacTypes.h>
- #include <Fonts.h>
- #include <Multiprocessing.h>
-
- #include <stdio.h> // for printf & fflush
- #include <SIOUX.h> // for SIOUXSettings stuff
- #include <SIOUXGlobals.h> // for SIOUXQuitting
- //**************************************************
- #pragma mark typedefs, structs, enums, defines, etc.
- //**************************************************
- #define REGISTER_DEBUGGER 1 // 0 == MPSetExceptionHandler, 0 != MPRegisterDebugger
- #define USE_STATE 1 // !0 == set & log task state variable
- #define USE_TRAP 1 // 0 == System Call, !0 == trap instruction
- //**************************************************
- #if USE_STATE
- #define SET_STATE(x) { gState = (x);}
- #define GET_STATE() (gState)
- #define LOG_STATE(s) {printf("%s; GET_STATE() = %8.8lX.\n",(s),GET_STATE());}
- #else
- #define SET_STATE(x) {}
- #define GET_STATE() (-1)
- #define LOG_STATE(s) {}
- #endif USE_STATE
- //**************************************************
- #pragma mark static (local) function prototypes
- //**************************************************
- #if USE_TRAP
- static asm UInt32 TRAP(const SInt32 pR3,const SInt32 pR4);
-
- static asm UInt32 TRAP_EQ(const SInt32 pR3,const SInt32 pR4);
- static asm UInt32 TRAP_NE(const SInt32 pR3,const SInt32 pR4);
- static asm UInt32 TRAP_LT(const SInt32 pR3,const SInt32 pR4);
- static asm UInt32 TRAP_GT(const SInt32 pR3,const SInt32 pR4);
- static asm UInt32 TRAP_LE(const SInt32 pR3,const SInt32 pR4);
- static asm UInt32 TRAP_GE(const SInt32 pR3,const SInt32 pR4);
-
- static asm UInt32 TRAP_LEQ(const UInt32 pR3,const UInt32 pR4);
- static asm UInt32 TRAP_LNE(const UInt32 pR3,const UInt32 pR4);
- static asm UInt32 TRAP_LLT(const UInt32 pR3,const UInt32 pR4);
- static asm UInt32 TRAP_LGT(const UInt32 pR3,const UInt32 pR4);
- static asm UInt32 TRAP_LLE(const UInt32 pR3,const UInt32 pR4);
- static asm UInt32 TRAP_LGE(const UInt32 pR3,const UInt32 pR4);
- #else
- static asm UInt32 System_Call(const UInt32 pR3);
- #endif USE_TRAP
- static OSStatus MyTask(void *parameter);
- static OSStatus Poll_MPTaskQueues(void);
- //**************************************************
- #pragma mark typedefs, structs, enums, defines, etc.
- //**************************************************
- static MPTaskID gMPTaskID = kInvalidID;
- static MPSemaphoreID gMPSemaphoreID = kInvalidID;
- static MPQueueID gMPQueueID = kInvalidID;
- static OSStatus gOSStatus = noErr;
- #if USE_STATE
- static UInt32 gState = -1;
- #endif USE_STATE
- static UInt32 gPass = 5;
- //**************************************************
- #pragma mark exported functions
- //**************************************************
- void main(void)
- {
- OSStatus anErr;
- volatile Boolean done = false;
-
- // Set the SIOUX window defaults
- SIOUXSettings.autocloseonquit = false;
- SIOUXSettings.asktosaveonclose = false;
- SIOUXSettings.showstatusline = false;
- SIOUXSettings.columns = 132;
- SIOUXSettings.rows = 24;
- SIOUXSettings.fontsize = 10;
- GetFNum("\pMonaco",&SIOUXSettings.fontid);
- SIOUXSettings.standalone = true;
-
- printf("MPExceptionTest starting!\n");
-
- // Make sure that the MP library is loaded
- if (!MPLibraryIsLoaded())
- {
- printf("The MP library did not load.\n");
- return;
- }
-
- { // for giggles we'll dump out the MP Library version info
- Ptr tVersionCStringPtr;
- UInt32 major,minor,release,revision;
-
- _MPLibraryVersion(&tVersionCStringPtr,&major,&minor,&release,&revision);
-
- printf("\n Version: \"%s\", major: %ld, minor: %ld, release: %ld, revision: %ld.\n",tVersionCStringPtr,major,minor,release,revision);
- }
-
- // create our trigger semaphore
- anErr = MPCreateSemaphore(1,0,&gMPSemaphoreID);
- if (noErr != anErr)
- printf("MPCreateSemaphore error: %ld.\n", anErr);
- else
- printf("Trigger semaphore created...\n");
-
- SET_STATE(0);
- LOG_STATE("Initializing state");
-
- // create our task
- anErr = MPCreateTask(MyTask, (void *) &gMPSemaphoreID,0,kInvalidID,nil,nil,kNilOptions,&gMPTaskID);
- if (noErr != anErr)
- printf("MPCreateTask error: %ld.\n", anErr);
- else
- printf("Task created...\n");
-
- LOG_STATE("After MPCreateTask");
-
- // create the exception queue
- anErr = MPCreateQueue(&gMPQueueID);
- if (noErr != anErr)
- printf("MPCreateQueue error: %ld.\n", anErr);
- else
- printf("exception Queue created...\n");
-
- #if REGISTER_DEBUGGER
- anErr = MPRegisterDebugger(gMPQueueID,100);
- if (noErr != anErr)
- printf("MPRegisterDebugger error: %ld.\n", anErr);
- else
- printf("Debugger registered...\n");
- #else
- // set the exception queue for our task
- anErr = MPSetExceptionHandler(gMPTaskID,gMPQueueID);
- if (noErr != anErr)
- printf("MPSetExceptionHandler error: %ld.\n", anErr);
- else
- printf("ExceptionHandler set...\n");
- #endif REGISTER_DEBUGGER
-
- LOG_STATE("Before MPSignalSemaphore");
-
- // trigger the task to throw an exception
- anErr = MPSignalSemaphore(gMPSemaphoreID);
- if (noErr != anErr)
- printf("MPSignalSemaphore error: %ld.\n", anErr);
- else
- printf("Semaphore signaled...\n");
-
- LOG_STATE("After MPSignalSemaphore");
-
- // it's importaint that our WaitNextEvent loop not be CPU bound
- // so we use a sleep time of one with WNE.
- while (!done && (noErr == anErr) && !SIOUXQuitting)
- {
- EventRecord theEvent;
-
- WaitNextEvent(everyEvent,&theEvent,1,nil);
- SIOUXHandleOneEvent(&theEvent); // tell SIOUX to handle the event
-
- anErr = Poll_MPTaskQueues();
- }
-
- #if REGISTER_DEBUGGER
- if (noErr == anErr)
- anErr = MPUnregisterDebugger(gMPQueueID);
- else
- (void) MPUnregisterDebugger(gMPQueueID);
- #endif REGISTER_DEBUGGER
-
- // Now cleanup (delete) our trigger semaphore, task & exception queue.
- if (kInvalidID != gMPSemaphoreID)
- MPDeleteSemaphore(gMPSemaphoreID);
-
- if (kInvalidID != gMPTaskID)
- MPTerminateTask(gMPTaskID,-1);
-
- if (kInvalidID != gMPQueueID)
- MPDeleteQueue(gMPQueueID);
-
- // if we had an error then report it
- if (noErr != anErr)
- printf("Error: %ld.",anErr);
-
- if (noErr == anErr)
- printf("Done!\n");
-
- // printf("Press command-Q to quit.");
- }
- //**************************************************
- #pragma mark static (local) functions
- //**************************************************
- #if USE_TRAP
- static asm UInt32 TRAP(/* const SInt32 pR3,const SInt32 pR4 */)
- {
- tw 0x1F,r3,r4 // LT | GT | EQ | LO | HI (trap r3,r4)
- blr
- }
-
- static asm UInt32 TRAP_EQ(/* const SInt32 pR3,const SInt32 pR4 */)
- {
- tweq r3,r4
- blr
- }
- static asm UInt32 TRAP_NE(/* const SInt32 pR3,const SInt32 pR4 */)
- {
- twne r3,r4
- blr
- }
- static asm UInt32 TRAP_LT(/* const SInt32 pR3,const SInt32 pR4 */)
- {
- twlt r3,r4 // LT
- blr
- }
- static asm UInt32 TRAP_GT(/* const SInt32 pR3,const SInt32 pR4 */)
- {
- twgt r3,r4 // GT
- blr
- }
- static asm UInt32 TRAP_LE(/* const SInt32 pR3,const SInt32 pR4 */)
- {
- twle r3,r4 // LT | EQ
- blr
- }
- static asm UInt32 TRAP_GE(/* const SInt32 pR3,const SInt32 pR4 */)
- {
- twge r3,r4 // GT | EQ
- blr
- }
-
- static asm UInt32 TRAP_LEQ(/* const UInt32 pR3,const UInt32 pR4 */)
- {
- tweq r3,r4
- blr
- }
- static asm UInt32 TRAP_LNE(/* const UInt32 pR3,const UInt32 pR4 */)
- {
- twne r3,r4
- blr
- }
- static asm UInt32 TRAP_LLT(/* const UInt32 pR3,const UInt32 pR4 */)
- {
- twllt r3,r4 // LT
- blr
- }
- static asm UInt32 TRAP_LGT(/* const UInt32 pR3,const UInt32 pR4 */)
- {
- twlgt r3,r4 // GT
- blr
- }
- static asm UInt32 TRAP_LLE(/* const UInt32 pR3,const UInt32 pR4 */)
- {
- twlle r3,r4 // LT | EQ
- blr
- }
- static asm UInt32 TRAP_LGE(/* const UInt32 pR3,const UInt32 pR4 */)
- {
- twlge r3,r4 // GT | EQ
- blr
- }
- #else
- // This is used to throw a system call exception
- static asm UInt32 System_Call(/* const UInt32 pR3 */)
- {
- sc
- blr
- }
- #endif
-
- // This is our MP task
- static OSStatus MyTask(void *parameter)
- {
- OSErr anErr = noErr;
- SInt32 count = 0;
-
-
- if (noErr == anErr)
- {
- while (noErr == anErr)
- {
- SET_STATE(1);
- anErr = MPWaitOnSemaphore(*(MPSemaphoreID*) parameter,kDurationForever);
-
- SET_STATE(2);
-
- if (noErr == anErr)
- #if USE_TRAP
- anErr = TRAP(count++,0);
- #else
- anErr = System_Call(count++);
- #endif USE_TRAP
- SET_STATE(3);
- }
- SET_STATE(4);
- }
-
- // and return our status.
- return anErr;
- }
-
- static OSStatus Poll_MPTaskQueues(void)
- {
- SInt32 expMPTaskID,expType,p3;
- OSStatus anErr = noErr;
-
- // see if our exception queue has anything for us
- anErr = MPWaitOnQueue(gMPQueueID,(void*) &expMPTaskID,(void*) &expType,(void*) &p3,kDurationImmediate);
- if (kMPTimeoutErr == anErr) // if queue not ready yet...
- anErr = noErr; // ... ignore the error
- else if (noErr == anErr) // otherwise...
- {
- MachineInformationPowerPC tMachineInfo;
- RegisterInformationPowerPC tRegisterInfo;
- UInt32 *tUInt32Ptr,tUInt32;
-
- // ... let us know!
- printf("•exception queue notified of task #%8.8lX - ",expMPTaskID,expType,gPass);
-
- switch (expType)
- {
- case kUnknownException:
- printf("Unknown exception.\n");
- break;
- case kIllegalInstructionException:
- printf("Illegal Instruction exception.\n");
- break;
- case kTrapException:
- printf("Trap exception.\n");
- break;
- case kAccessException:
- printf("Access exception.\n");
- break;
- case kUnmappedMemoryException:
- printf("Unmapped memory exception.\n");
- break;
- case kExcludedMemoryException:
- printf("Excluded memory exception.\n");
- break;
- case kReadOnlyMemoryException:
- printf("Read-only memory exception.\n");
- break;
- case kUnresolvablePageFaultException:
- printf("Unresolvable page fault exception.\n");
- break;
- case kPrivilegeViolationException:
- printf("Privilege violation exception.\n");
- break;
- case kTraceException:
- printf("Trace exception.\n");
- break;
- case kInstructionBreakpointException:
- printf("Instruction breakpoint exception.\n");
- break;
- case kDataBreakpointException:
- printf("Data breakpoint exception.\n");
- break;
- case kIntegerException:
- printf("Integer exception.\n");
- break;
- case kFloatingPointException:
- printf("Floating point exception.\n");
- break;
- case kStackOverflowException:
- printf("Stack overflow exception.\n");
- break;
- case kTaskTerminationException:
- printf("Task termination exception.\n");
- break;
- case kTaskCreationException:
- printf("Task creation exception.\n");
- break;
- default:
- printf("Undefined exception type: %8.8lX.\n",expType);
- break;
- }
-
- LOG_STATE(" After exception");
-
- anErr = MPExtractTaskState(gMPTaskID,kMPTaskStateMachine,&tMachineInfo);
- if (noErr != anErr)
- printf(" MPExtractTaskState(%8.8lX,kMPTaskStateMachine) error: %ld.\n",
- gMPTaskID, anErr);
- else
- {
- printf(" Task machine state extracted. ");
-
- tUInt32Ptr = (UInt32*) tMachineInfo.PC.lo;
- tUInt32 = *tUInt32Ptr;
- #if USE_TRAP
- if (0x7FE32008 != tUInt32) // if this wasn't a trap instruction...
- #else
- if (0x44000002 != tUInt32) // if this wasn't a system call instruction...
- #endif USE_TRAP
- printf("(PC: %8.8lX, instruction @ PC: %8.8lX)\n",tUInt32Ptr,tUInt32);
- else
- {
- #if USE_TRAP
- printf("(PC: %8.8lX, instruction @ PC: %8.8lX (trap))\n",tUInt32Ptr,tUInt32);
- #else
- printf("(PC: %8.8lX, instruction @ PC: %8.8lX (System call))\n",tUInt32Ptr,tUInt32);
- #endif USE_TRAP
-
- tMachineInfo.PC.lo += 4; // ...skip past the instruction.
-
- anErr = MPSetTaskState(gMPTaskID,kMPTaskStateMachine,&tMachineInfo);
- if (noErr != anErr)
- printf(" MPSetTaskState(%8.8lX,kMPTaskStateMachine) error: %ld.\n",gMPTaskID, anErr);
- else
- printf(" Task machine state set (PC += 4).\n");
-
- anErr = MPExtractTaskState(gMPTaskID,kMPTaskStateRegisters,&tRegisterInfo);
- if (noErr != anErr)
- printf(" MPExtractTaskState(%8.8lX,kMPTaskStateRegisters) error: %ld.\n",
- gMPTaskID, anErr);
- else
- {
- printf(" Task register state extracted (R3: %8.8lX).\n",tRegisterInfo.R3.lo);
-
- if (0 == gPass) // if this is the last time...
- tRegisterInfo.R3.lo = -1; // ... then this will return an error!
- else // ... otherwise ...
- tRegisterInfo.R3.lo = 0; // ... it won't!
-
- anErr = MPSetTaskState(gMPTaskID,kMPTaskStateRegisters,&tRegisterInfo);
- if (noErr != anErr)
- printf(" MPSetTaskState(%8.8lX,kMPTaskStateRegisters) error: %ld.\n",gMPTaskID, anErr);
- else
- printf(" Task register state set (R3: %8.8lX).\n",tRegisterInfo.R3.lo);
- }
- }
- }
-
- // now dispose of the exception and resume the task.
- anErr = MPDisposeTaskException(gMPTaskID,kMPTaskResumeMask);
- if (noErr != anErr)
- printf(" MPDisposeTaskException error: %ld.\n", anErr);
- else
- printf(" Exception Disposed...\n");
-
- LOG_STATE(" After MPDisposeTaskException");
-
- if (0 < gPass)
- {
- gPass--;
-
- // trigger the task to throw an exception
- anErr = MPSignalSemaphore(gMPSemaphoreID);
- if (noErr != anErr)
- printf(" MPSignalSemaphore error: %ld.\n", anErr);
- else
- printf(" Semaphore signaled...\n");
- }
- }
-
- if (noErr != gOSStatus)
- {
- printf("•Task Error: %ld.\n",gOSStatus);
- gOSStatus = noErr;
- }
- return anErr;
- }
-